package com.m3958.firstgwt.server.servlet;

import java.io.IOException;
import java.util.Date;
import java.util.UUID;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.crypto.AesCipherService;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.apache.shiro.util.ByteSource;

import com.google.common.base.Charsets;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.m3958.firstgwt.server.dao.UserDao;
import com.m3958.firstgwt.server.model.User;
import com.m3958.firstgwt.server.service.AppUtilService;
import com.m3958.firstgwt.server.session.ErrorMessages;
import com.m3958.firstgwt.server.session.SessionUser;
import com.m3958.firstgwt.server.types.SmartError;

@Singleton
public class VerifyMeServlet  extends HttpServlet {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static byte[] VERIFY_CIPHER_KEY = new byte[]{-54, -72, 63, -39, -4, -79, 62, -47, -106, -9, -116, -63, -46, -71, -15, -12};
	
	@Inject
	protected com.google.inject.Provider<EntityManager> emp;
	
	@Inject
	private Injector injector;
	
	@Inject
	private AppUtilService autils;
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		

	Optional<String> v = Optional.of(req.getParameter("v"));
	//decode
	byte[] ciphertext = Base64.decode(v.get());
	AesCipherService veriryAesCipherService = new AesCipherService();
	ByteSource plainText = veriryAesCipherService.decrypt(ciphertext, VERIFY_CIPHER_KEY);
	String verifyStr = new String(plainText.getBytes(),Charsets.UTF_8);
	String[] hashAndJsonStr = verifyStr.split("=", 2);
	String vtJsonStrHashedBase64 = hashAndJsonStr[0] + "=";
	String vtJsonStr = hashAndJsonStr[1];
	String vtJsonStrHashedBase642 = new Sha256Hash(vtJsonStr).toBase64();
	if(!vtJsonStrHashedBase64.equals(vtJsonStrHashedBase642)){
		autils.writeHtmlResponseWithTemplate(res, "<p>验证错误!</p><p style=\"display:none;\">" + vtJsonStrHashedBase64 + " ||| "  + vtJsonStrHashedBase642  + "</p>");
		return;
	}
	
	JSONObject vt = JSONObject.fromObject(vtJsonStr);
	
	//check remoteIp
	
	String remoteip = Strings.emptyToNull((req.getParameter("remoteip"))); 
	if(remoteip == null){
		remoteip = req.getRemoteAddr();
	}
	if(!remoteip.equals(vt.getString("remoteIp"))){
		autils.writeHtmlResponseWithTemplate(res, "<p>验证错误!</p><p style=\"display:none;\">" + remoteip + " ||| "  + vt.getString("remoteIp")  + "</p>");
		return;
	}
	

	HttpClient httpclient = new DefaultHttpClient();
	HttpGet httpget = new HttpGet("http://accounts.m3958.com/domain/ConsumeToken?dowhat=verifyToken&token=" + vt.getString("uuid"));
	HttpResponse response = httpclient.execute(httpget);
	HttpEntity entity = response.getEntity();
	if (entity != null) {
		String c = EntityUtils.toString(entity, Charsets.UTF_8);
//		getServletContext().log(c);
		JSONObject ajr = JSONObject.fromObject(c);
		JSONArray ja = ajr.getJSONArray("datas");
		if(ja.size() != 1)return;
		if(!v.get().equals(ja.getJSONObject(0).getString("longToken"))){
			autils.writeHtmlResponseWithTemplate(res, "<p>验证错误!</p><p style=\"display:none;\">" + v.get() + " ||| "  + ja.getJSONObject(0).getString("longToken")  + "</p>");
			return;
		}
	}
	String qs = "SELECT u FROM User as u WHERE u.m3958UserId = :m3958UserId";
	TypedQuery<User> q = emp.get().createQuery(qs,User.class);
	q.setParameter("m3958UserId", vt.getLong("m3958UserId"));
	User u = null;
	try {
		u = q.getSingleResult();
	} catch (NoResultException e) {
		;
	}
	SessionUser su = injector.getInstance(SessionUser.class);
	if(u == null){
		UserDao udao = injector.getInstance(UserDao.class);
		String uuid = UUID.randomUUID().toString();
		u = new User();
		if(vt.getString("nickname") == null || vt.getString("nickname").isEmpty()){
			u.setLoginName(vt.getString("nickname") + '-' + uuid);
		}else{
			u.setLoginName(uuid);
		}
		Date d  = new Date();
		String email = vt.getString("email"); 
		if(email == null || email.isEmpty()){
			u.setEmail(uuid + "@m3958.com");
		}else{
			User au = udao.findByEmail(email);
			if(au != null){
				u.setEmail(d.getTime() + "-" + email );
			}else{
				u.setEmail(email);
			}
		}
		
		u.setMobile("86" + d.getTime());
		u.setM3958UserId(vt.getLong("m3958UserId"));
		u.setCreatedAt(d);
		u.setPassword(uuid);
		HttpSession se = req.getSession(true);
		se.setAttribute("skipRequestParameterValidate", true);
		udao.smartPersistBaseModel(u);
	}
	
	ErrorMessages errors = injector.getInstance(ErrorMessages.class);
	if(errors.isEmpty()){
		su.setContent(u);
//		String next = vt.getString("next");
		res.sendRedirect("http://www.m3958.com/in");
	}else{
		for(SmartError er : errors.getErrors()){
			System.out.println(er.getCode() + "," + er.getMessage());
		}
	}
	}
}
